home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / memprot.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  32KB  |  1,148 lines

  1. /*
  2.  * Copyright 1991,1992,1993 Atari Corporation.
  3.  * All rights reserved.
  4.  */
  5.  
  6. /*
  7.  * page-table data structures
  8.  *
  9.  *
  10.  * The root pointer points to a list of pointers to top-level pointer tables.
  11.  * 
  12.  * Each entry in a pointer table points to another pointer table or to
  13.  * a page table, or is a page descriptor.
  14.  * 
  15.  * Since, initially, the logical address space is the physical address space,
  16.  * we only need to worry about 26MB plus 32K for I/O space.
  17.  * 
  18.  * Since we want some pages to be supervisor-accessible, but we don't want
  19.  * a whole separate table for that, we use long-format descriptors.
  20.  * 
  21.  * Initial memory map:
  22.  * 
  23.  * 0     - membot: S (supervisor only)
  24.  * membot     - memtop: P (protected TPA)
  25.  * memtop     - phystop: G (screen)
  26.  * phystop     - $00E00000: bus error
  27.  * $00E00000- $00E3FFFF: G (ROM)
  28.  * $00E40000- $00FF7FFF: bus error
  29.  * $00FF8000- $00FFFFFF: G (mostly S: I/O space, but that's done in hardware)
  30.  * $01000000- ramtop: P
  31.  * ramtop     - $7FFFFFFF: G (A32/D32 VME, cacheable)
  32.  * $80000000- $FEFFFFFF: G (A32/D32 VME, non cacheable)
  33.  * $FFxxxxxx          just like $00xxxxxx.
  34.  * 
  35.  * Here's a final choice of layouts: IS=0, PS=13 (8K), TIA=4, TIB=4, TIC=4,
  36.  * TID=7.  This lets us map out entire unused megabytes at level C, and gives
  37.  * us an 8K page size, which is the largest the '040 can deal with.
  38.  * 
  39.  * This code implements 4+4+4+7, as follows:
  40.  * 
  41.  * tbl_a
  42.  *     0 -> tbl_b0
  43.  *     1-7 -> Cacheable direct (VME) page descriptors
  44.  *     8-E -> Non-cacheable direct (VME) page descriptors
  45.  *     F -> tbl_bf
  46.  * 
  47.  * tbl_b0 table: 16 entries (assumes only 16MB of TT RAM)
  48.  *     0 -> tbl_c00 (16MB of ST RAM address space)
  49.  *     1 -> tbl_c01 (16MB of TT RAM address space)
  50.  *     2-F -> cacheable direct (VME) page descriptors
  51.  * 
  52.  * tbl_bF table: 16 entries (deals with $FF mapping to $00)
  53.  *     0-E -> Non-cacheable direct (VME) page descriptors
  54.  *     F -> tbl_c00 (16MB of ST RAM address space, repeated here as $FF)
  55.  * 
  56.  * tbl_c00 table: ST RAM address space (example assuming 4MB ST RAM)
  57.  *     0-3 -> RAM page tables
  58.  *     4-D -> invalid
  59.  *     E -> direct map, cache enable (ROM)
  60.  *     F -> direct map, cache inhibit (I/O)
  61.  * 
  62.  * For each 16MB containing any TT RAM, there's a tbl_c.  Within those,
  63.  * for each MB that actually has TT RAM, there's another table, containing
  64.  * 128 RAM page tables.  Where there isn't RAM, there are "global"
  65.  * pages, to let the hardware bus error or not as it sees fit.
  66.  * 
  67.  * One RAM page table is allocated per megabyte of real RAM; each table has
  68.  * 128 entries, which is 8K per page.  For a TT with 4MB ST RAM and 4MB TT RAM
  69.  * that's 8K in page tables.  You can cut this down by not allocating page
  70.  * tables for which the entire megabyte is not accessible (i.e. it's all
  71.  * private memory and it's not YOUR private memory).
  72.  * 
  73.  * You have one of these per process.  When somebody loads into G or S memory
  74.  * or leaves it, you have to go through the page tables of every process
  75.  * updating S bits (for S) and DT (for G) bits.
  76.  * 
  77.  * The top levels are small & easy so replicating them once per process
  78.  * doesn't really hurt us.
  79.  * 
  80.  */
  81.  
  82. #include "mint.h"
  83.  
  84. #if 0
  85. #define MP_DEBUG(x) DEBUG(x)
  86. #else
  87. #define MP_DEBUG(x)
  88. #endif
  89.  
  90. void *memset P_((void *s, int ucharfill, unsigned long size));
  91. static void _dump_tree P_((long_desc tbl, int level));
  92.  
  93. extern int debug_level;        /* see debug.c */
  94.  
  95. /*
  96.  * You can turn this whole module off, and the stuff in context.s,
  97.  * by setting no_mem_prot to 1.
  98.  */
  99.  
  100. int no_mem_prot;
  101. long page_table_size;
  102.  
  103. /*
  104.  * PMMU stuff
  105.  */
  106. #if 1
  107. #define flush_pmmu(start, end) __asm("pflusha")
  108. #else
  109. /* in cpu.spp is a new "cpush" function that can selectively flush
  110.  * the cache
  111.  */
  112. #define flush_pmmu(start, len) cpush((void *)(start), (long)(len))
  113. #endif
  114.  
  115. /*
  116.  * This is one global TC register that is copied into every process'
  117.  * context, even though it never changes.  It's also used by the
  118.  * functions that dump page tables.
  119.  */
  120.  
  121. tc_reg tc;
  122.  
  123. /* mint_top_* get used in mem.c also */
  124. ulong mint_top_tt;
  125. ulong mint_top_st;
  126.  
  127. int tt_mbytes;        /* number of megabytds of TT RAM */
  128.  
  129. /*
  130.  * global_mode_table: one byte per page in the system.  Initially all pages
  131.  * are set to "global" but then the TPA pages are set to "invalid" in
  132.  * init_mem.  This has to be allocated and initialized in init_tables,
  133.  * when you know how much memory there is.  You need a byte per page,
  134.  * from zero to the end of TT RAM, including the space between STRAM
  135.  * and TTRAM.  That is, you need 16MB/pagesize plus (tt_mbytes/pagesize)
  136.  * bytes here.
  137.  */
  138.  
  139. unsigned char *global_mode_table;
  140.  
  141. /*
  142.  * prototype descriptors; field u1 must be all ones, other u? are zero.
  143.  * This is just the first long of a full descriptor; the ".page_type" part
  144.  * of the union.  These are initialized by init_tables.
  145.  *
  146.  * The proto_page_type table yields the value to stuff into the page_type
  147.  * field of a new process' page table.  It is the "non-owner" mode for
  148.  * a page with the corresponding value in global_mode_table.
  149.  */
  150.  
  151. page_type g_page;
  152. page_type g_ci_page;
  153. page_type s_page;
  154. page_type readable_page;
  155. page_type invalid_page;
  156. page_type page_ptr;
  157.  
  158. page_type *proto_page_type[] =
  159.     { &invalid_page, &g_page, &s_page, &readable_page, &invalid_page };
  160. /*    private         global    super    private/read    invalid */
  161.  
  162. /*
  163.  * Init_tables: called sometime in initialization.  We set up some
  164.  * constants here, but that's all.  The first new_proc call will set up the
  165.  * page table for the root process and switch it in; from then on, we're
  166.  * always under some process' control.
  167.  * 
  168.  * The master page-mode table is initialized here, and some constants like
  169.  * the size needed for future page tables.
  170.  *
  171.  * One important constant initialized here is page_table_size, which is
  172.  * the amount of memory required per page table.  new_proc allocates
  173.  * this much memory for each process' page table.  This number will be
  174.  * 1K/megabyte plus page table overhead.  There are TBL_PAGES_OFFS
  175.  * tables at TBL_SIZE_BYTES each before the main tables begin; then
  176.  * there is 1024 bytes per megabyte of memory being mapped.
  177.  */
  178.  
  179. void
  180. init_tables()
  181. {
  182.     int n_megabytes;
  183.     long global_mode_table_size;
  184.  
  185.     if (no_mem_prot) return;
  186.  
  187.     TRACE(("init_tables"));
  188.  
  189. #define phys_top_tt (*(ulong *)0x5a4L)
  190.     if (phys_top_tt == 0x01000000L) mint_top_tt = 0;
  191.     else mint_top_tt = phys_top_tt;
  192.  
  193. #define phys_top_st (*(ulong *)0x42eL)
  194.     mint_top_st = phys_top_st;
  195.  
  196.     if (mint_top_tt)
  197.         tt_mbytes = (int) ((mint_top_tt - 0x01000000L) / ONE_MEG);
  198.     else
  199.         tt_mbytes = 0;
  200.  
  201.     n_megabytes = (int) ((mint_top_st / ONE_MEG) + tt_mbytes);
  202.  
  203.     /*
  204.      * page table size: room for A table, B0 table, BF table, STRAM C
  205.      * table, one TTRAM C table per 16MB (or fraction) of TTRAM, and 1024
  206.      * bytes per megabyte.
  207.      */
  208.  
  209.     page_table_size = (4L * TBL_SIZE_BYTES) +
  210.               (((tt_mbytes+15L)/16L) * TBL_SIZE_BYTES) +
  211.               (n_megabytes*1024L);
  212.  
  213.     global_mode_table_size = ((SIXTEEN_MEG / QUANTUM) +
  214.                 (((ulong)tt_mbytes * ONE_MEG) / QUANTUM));
  215.  
  216.     global_mode_table = kmalloc(global_mode_table_size);
  217.  
  218.     assert(global_mode_table);
  219.  
  220.     TRACELOW(("mint_top_st is $%lx; mint_top_tt is $%lx, n_megabytes is %d",
  221.     mint_top_st, mint_top_tt, n_megabytes));
  222.     TRACELOW(("page_table_size is %ld, global_mode_table_size %ld",
  223.         page_table_size,
  224.         global_mode_table_size));
  225.  
  226.     g_page.limit = 0x7fff;    /* set nonzero fields: disabled limit */
  227.     g_page.unused1 = 0x3f;    /* ones in this reserved field */
  228.     g_page.unused2 = 0;
  229.     g_page.s = 0;
  230.     g_page.unused3 = 0;
  231.     g_page.ci = 0;
  232.     g_page.unused4 = 0;
  233.     g_page.m = 1;        /* set m and u to 1 so CPU won't do writes */
  234.     g_page.u = 1;
  235.     g_page.wp = 0;        /* not write-protected */
  236.     g_page.dt = 1;        /* descriptor type 1: page descriptor */
  237.  
  238.     g_ci_page = g_page;
  239.     g_ci_page.ci = 1;
  240.  
  241.     readable_page = g_page;    /* a page which is globally readable */
  242.     readable_page.wp = 1;    /* but write protected */
  243.  
  244.     s_page = g_page;        /*